package com.example.androidtest.demo3

import android.util.Log
import io.netty.bootstrap.Bootstrap
import io.netty.channel.*
import io.netty.handler.timeout.IdleState
import io.netty.handler.timeout.IdleStateEvent
import io.netty.util.Timeout
import io.netty.util.Timer
import io.netty.util.TimerTask
import io.netty.channel.socket.SocketChannel
import io.netty.util.concurrent.GenericFutureListener
import java.util.*
import java.util.concurrent.TimeUnit

//创建接口
interface ChannelHandlerHolder {

    fun handlers(): Array<ChannelHandler>
}

//创建接口
interface ReconnectSuccessHolder {

    fun reconnectSuccess(channel: SocketChannel?)
}

/**
 * 连接监控器
 * */
@ChannelHandler.Sharable
abstract class ConnectionWatchdog(
    val bootstrap: Bootstrap,
    val timer: Timer,
    val port: Int,
    val host: String,
    val reconnect: Boolean
) : ChannelInboundHandlerAdapter(), TimerTask, ChannelHandlerHolder, ReconnectSuccessHolder {


    private var attempts: Int = 0

    //TimerTask接口的方法
    override fun run(p0: Timeout?) {
        //bootstrap已经初始化好了，只需要将handler填入就可以了
        val future: ChannelFuture = synchronized(bootstrap) {

            bootstrap.handler(object : ChannelInitializer<Channel>() {
                @Throws(Exception::class)
                override fun initChannel(ch: Channel) {
                    ch.pipeline()
                        .addLast(*handlers())
                }
            })
            bootstrap.connect(host, port)
        }
        //future对象
        future.addListener { f ->
            val succeed = f.isSuccess

            //如果重连失败，则调用ChannelInactive方法，再次出发重连事件，一直尝试12次，如果失败则不再重连
            if (!succeed) {
//                Log.i("netty", "重连失败")
                (f as ChannelFuture).channel().pipeline().fireChannelInactive()
            } else {
                val socketChannel = future.channel() as SocketChannel
                reconnectSuccess(socketChannel)
//                Log.i("netty", "重连成功")
            }
        }
    }


    override fun channelInactive(ctx: ChannelHandlerContext?) {
        super.channelInactive(ctx)
//        Log.i("netty", "链接关闭")
        if(reconnect){


//            Log.i("netty", "链接关闭，将进行重连")
            //重连的间隔时间会越来越长
            timer.newTimeout(this, 10, TimeUnit.SECONDS)
        }
        ctx!!.fireChannelInactive()
    }

    override fun channelActive(ctx: ChannelHandlerContext?) {
        super.channelActive(ctx)
//        Log.i("netty", "当前链路已经激活了，重连尝试次数重新置为0")
        attempts = 0
        ctx!!.fireChannelActive()

    }
}



/**
 * 连接空闲处理
 * */
@ChannelHandler.Sharable
class ConnectorIdleStateTrigger : ChannelInboundHandlerAdapter() {

    override fun userEventTriggered(ctx: ChannelHandlerContext?, evt: Any?) {
        super.userEventTriggered(ctx, evt)

        if (evt is IdleStateEvent) {
            val state = evt.state()
            if (state == IdleState.WRITER_IDLE) {
                // write heartbeat to server
//                Log.i("netty", "IdleState.WRITER_IDLE")
//                Log.i("NettyBeatLog", "空闲");
                NettyClient.getInstance().ping()
            }
            if( state == IdleState.READER_IDLE) {
//                Log.i("netty", "IdleState.READER_IDLE")
//                Log.i("NettyBeatLog", "长时间没收到数据");
                ctx!!.disconnect()
            }
        } else {
            super.userEventTriggered(ctx, evt)
        }
    }
}
